import compose from './compose'

/**
 * Creates a store enhancer that applies middleware to the dispatch method
 * of the Redux store. This is handy for a variety of tasks, such as expressing
 * asynchronous actions in a concise manner, or logging every action payload.
 *
 * See `redux-thunk` package as an example of the Redux middleware.
 *
 * Because middleware is potentially asynchronous, this should be the first
 * store enhancer in the composition chain.
 *
 * Note that each middleware will be given the `dispatch` and `getState` functions
 * as named arguments.
 *
 * @param middlewares The middleware chain to be applied.
 * @returns A store enhancer applying the middleware.
 *
 * @template Ext Dispatch signature added by a middleware.
 * @template S The type of the state supported by a middleware.
 */

export default function applyMiddleware(...middlewares) {
  return createStore => {
    return (reducer, preloadedState) => {
      const store = createStore(reducer, preloadedState)
      let dispatch = () => {
        throw new Error(
          'Dispatching while constructing your middleware is not allowed. ' +
            'Other middleware would not be applied to this dispatch.'
        )
      }
      /*
       * 构建增强dispatch需要的两个函数参数
       * 1.getState 为 store 原生方法
       * 2.dispatch 功能提供api，并添加提前执行警告
       * */
      const middlewareAPI = {
        getState: store.getState,
        dispatch: (action, ...args) => dispatch(action, ...args)
      }
      // 像所有中间件注入函数参数
      const chain = middlewares.map(middleware => middleware(middlewareAPI))
      /*
       * 1.通过compose函数，按照顺序组合成高级函数
       * 2.注入store.dispatch原生函数
       * 3.返回一个增强的高级函数dispatch，使得可以拥有原生dispatch和增强dispatch两种函数的执行能力
       * */
      dispatch = compose(...chain)(store.dispatch)

      //通过展开符完成dispatch函数替换：普通函数--》高级函数
      return {
        ...store,
        dispatch
      }
    }
  }
}
